// 用于存放所有的游戏对象
const gameObjects = []
let isPaused = false

// 所有游戏对象的基类
export class GameObject {
    constructor() {
        gameObjects.push(this)
        // 初始化时间间隔为0，用于记录两帧之间的时间差
        this.timeDelta = 0
        // 标记该游戏对象是否已经调用过start方法
        this.hasCalledStart = false
    }

    // 静态方法，用于获取所有游戏对象
    static get_objects() {
        return gameObjects
    }

    // 静态方法，用于暂停游戏
    static pause_game() {
        isPaused = true
    }

    // 静态方法，用于恢复游戏
    static resume_game() {
        isPaused = false
    }

    // 静态方法，获取游戏暂停状态
    static is_game_paused() {
        return isPaused
    }

    // 静态方法，重置所有游戏对象
    static reset_game_objects() {
        // 创建副本以避免在遍历过程中修改原数组
        const objectsToDestroy = [...gameObjects]

        // 销毁所有游戏对象
        objectsToDestroy.forEach((obj) => {
            obj.destroy()
        })

        // 确保数组已清空
        gameObjects.length = 0

        // 重置暂停状态
        isPaused = false
    }

    // start方法, 在开始时只执行一次
    start() {}

    // update方法, 每一帧都会执行, 不包括第一帧
    update() {}

    // pre_destroy方法, 在对象被销毁前执行
    pre_destroy() {}

    // destroy方法, 用于销毁当前对象
    destroy() {
        this.pre_destroy()

        for (let i = 0; i < gameObjects.length; i++) {
            if (gameObjects[i] === this) {
                gameObjects.splice(i, 1)
                break
            }
        }
    }
}

// 用于存储上一帧的时间戳
let lastTimeStamp

// 动画循环
const step = (timeStamp) => {
    // 如果游戏暂停，只执行时间戳更新，不更新游戏对象
    if (isPaused) {
        lastTimeStamp = timeStamp
        requestAnimationFrame(step)
        return
    }
    for (let obj of gameObjects) {
        if (!obj.hasCalledStart) {
            obj.hasCalledStart = true
            obj.start()
        } else {
            // 如果已经调用过start, 计算当前帧和上一帧的时间差
            obj.timeDelta = timeStamp - lastTimeStamp
            // 每帧更新
            obj.update()
        }
    }

    // 更新lastTimeStamp为当前帧的时间戳
    lastTimeStamp = timeStamp

    // 请求浏览器在下一帧调用step函数, 实现动画循环
    requestAnimationFrame(step)
}

// 首次调用requestAnimationFrame启动动画循环
requestAnimationFrame(step)
